#pragma once

#include "t2sdk_interface.h"
#include <fmt/format.h>
#include <fmt/color.h>

#include <string>
#include <map>
#include <thread>

using namespace std;

map<string, string> AllRecords;

void ShowPacket(IF2UnPacker *lpUnPacker)
{
	int i = 0, t = 0, j = 0, k = 0;

	for (i = 0; i < lpUnPacker->GetDatasetCount(); ++i)
	{
		// 设置当前结果集
		lpUnPacker->SetCurrentDatasetByIndex(i);

		// 打印字段
		// for (t = 0; t < lpUnPacker->GetColCount(); ++t)
		//{
		//	printf("%20s", lpUnPacker->GetColName(t));
		//}

		// putchar('\n');

		// 打印所有记录
		for (j = 0; j < (int)lpUnPacker->GetRowCount(); ++j)
		{
			// 打印每条记录
			for (k = 0; k < lpUnPacker->GetColCount(); ++k)
			{
				const char *name = lpUnPacker->GetColName(k);
				switch (lpUnPacker->GetColType(k))
				{
				case 'I':
					// int value = lpUnPacker->GetIntByIndex(k);
					// printf("%20d", value);
					AllRecords.insert_or_assign(name, to_string(lpUnPacker->GetIntByIndex(k)));
					break;

				case 'C':
					// printf("%20c", lpUnPacker->GetCharByIndex(k));
					AllRecords.insert_or_assign(name, string{lpUnPacker->GetCharByIndex(k)});
					break;

				case 'S':
					// printf("%20s", lpUnPacker->GetStrByIndex(k));
					AllRecords.insert_or_assign(name, lpUnPacker->GetStrByIndex(k));
					break;

				case 'F':
					// printf("%20f", lpUnPacker->GetDoubleByIndex(k));
					AllRecords.insert_or_assign(name, to_string(lpUnPacker->GetDoubleByIndex(k)));
					break;

				case 'R':
				{
					int nLength = 0;
					void *lpData = lpUnPacker->GetRawByIndex(k, &nLength);

					// 对2进制数据进行处理
					break;
				}

				default:
					// 未知数据类型
					printf("未知数据类型。\n");
					break;
				}
				fmt::print("({}:{}),", name, AllRecords[name]);
			}

			printf("\n");

			lpUnPacker->Next();
		}

		printf("\n");
	}
}

class CCallback : public CCallbackInterface
{
public:
	CCallback() = default;
	// 因为CCallbackInterface的最终纯虚基类是IKnown，所以需要实现一下这3个方法
	unsigned long QueryInterface(const char *iid, IKnown **ppv)
	{
		return 0;
	}
	unsigned long AddRef()
	{
		return 0;
	}
	unsigned long Release()
	{
		return 0;
	}

	void OnConnect(CConnectionInterface *lpConnection)
	{
		printf("[OnConnect] CConnectionInterface = %p\n", lpConnection);
		fmt::print("[OnConnect]:{}\n", lpConnection->GetStatus());
	}

	void OnSafeConnect(CConnectionInterface *lpConnection)
	{
		fmt::print("[OnSafeConnect]:{}\n", lpConnection->GetStatus());
	}

	void OnRegister(CConnectionInterface *lpConnection)
	{
		fmt::print("[OnRegister]:{}\n", lpConnection->GetStatus());
	}

	void OnClose(CConnectionInterface *lpConnection)
	{
		fmt::print("[OnClose]:{}\n", lpConnection->GetStatus());
	}

	void OnSent(CConnectionInterface *lpConnection, int hSend, void *reserved1, void *reserved2, int nQueuingData)
	{
		fmt::print("[OnSent]:Status={}, SendHandle =\n", lpConnection->GetStatus(), hSend);
	}

	void OnReceivedBiz(CConnectionInterface *lpConnection, int hSend, const void *lpUnPackerOrStr, int nResult)
	{
	}

	void OnReceivedBizEx(CConnectionInterface *lpConnection, int hSend, LPRET_DATA lpRetData, const void *lpUnpackerOrStr, int nResult)
	{
	}

	void OnReceivedBizMsg(CConnectionInterface *lpConnection, int hSend, IBizMessage *lpMsg)
	{
		if (lpMsg == nullptr)
			return;

		int iReturnCode = lpMsg->GetReturnCode();
		if (iReturnCode == 1 || iReturnCode == -1) // 错误
		{
			printf("errorNo:%d,errorInfo:%s\n", lpMsg->GetErrorNo(), lpMsg->GetErrorInfo());
		}
		else if (iReturnCode == 0) // 正确
		{
			// 如果要把消息放到其他线程处理，必须自行拷贝，操作如下：
			// int iMsgLen = 0;
			// void * lpMsgBuffer = lpBizMessageRecv->GetBuff(iMsgLen);
			// 将lpMsgBuffer拷贝走，然后在其他线程中恢复成消息可进行如下操作：
			// lpBizMessageRecv->SetBuff(lpMsgBuffer,iMsgLen);
			// 没有错误信息
			printf("业务操作成功");
			int iLen = 0;
			const void *lpBuffer = lpMsg->GetContent(iLen);
			IF2UnPacker *lpUnPacker = NewUnPacker((void *)lpBuffer, iLen);
			ShowPacket(lpUnPacker);
		}
		else // 业务错误
		{
			// 有错误信息
			// int errorcode = lpConnection->GetLastAnsError(true);

			// fmt::print("业务操作失败: {}\n", lpConnection->GetLastAnsError(true));
			int iLen = 0;
			const void *lpBuffer = lpMsg->GetContent(iLen);
			IF2UnPacker *lpUnPacker = NewUnPacker((void *)lpBuffer, iLen);
			// ShowPacket(lpUnPacker);
			fmt::print("业务失败：{} = {}\n", lpUnPacker->GetInt("error_no"), lpUnPacker->GetStr("error_info"));
		}
	}

	void Reserved1(void *a, void *b, void *c, void *d) {}
	void Reserved2(void *a, void *b, void *c, void *d) {}
	int Reserved3() { return 0; }
	void Reserved4() {}
	void Reserved5() {}
	void Reserved6() {}
	void Reserved7() {}
};

// 订阅的消息回调
class CSubCallback : public CSubCallbackInterface
{
public:
	unsigned long FUNCTION_CALL_MODE QueryInterface(const char *iid, IKnown **ppv)
	{
		return 0;
	}
	unsigned long FUNCTION_CALL_MODE AddRef()
	{
		return 0;
	}
	unsigned long FUNCTION_CALL_MODE Release()
	{
		return 0;
	}

	void FUNCTION_CALL_MODE OnReceived(CSubscribeInterface *lpSub, int subscribeIndex, const void *lpData, int nLength, LPSUBSCRIBE_RECVDATA lpRecvData)
	{
		fmt::print("[OnReceived] lpSub={}, subscribeIndex={}, lpData={}, nLength={}\n",
				   fmt::ptr(lpSub), subscribeIndex, lpData, nLength);
		// fmt::print("lpRecvData=[ lpFilterData={}, iFilterDataLen={}, lpAppData={}, iAppDataLen={} ,szTopicName={} ]\n",
		//		   fmt::ptr(lpRecvData->lpFilterData), lpRecvData->iFilterDataLen, lpRecvData->lpAppData, lpRecvData->iAppDataLen, lpRecvData->szTopicName);

		// lpAppData - SetAppData设置的附加数据
		// lpFilterData - SetFilter设置的过滤数据

		IF2UnPacker *filterPack = NewUnPacker(lpRecvData->lpFilterData, lpRecvData->iFilterDataLen);
		filterPack->AddRef();
		while (!filterPack->IsEOF())
		{
			ShowPacket(filterPack);
			filterPack->Next();
		}
		filterPack->Release();

		IF2UnPacker *lpUnPack = NewUnPacker((void *)lpData, nLength);
		lpUnPack->AddRef();
		while (!lpUnPack->IsEOF())
		{
			ShowPacket(lpUnPack);
			lpUnPack->Next();
		}

		lpUnPack->Release();
	}

	void FUNCTION_CALL_MODE OnRecvTickMsg(CSubscribeInterface *lpSub, int subscribeIndex, const char *TickMsgInfo)
	{
		fmt::print("[OnRecvTickMsg]lpSub={},  subscribeIndex={}, TickMsgInfo={}\n",
				   fmt::ptr(lpSub), subscribeIndex,
				   TickMsgInfo != nullptr ? TickMsgInfo : "");
	}
};

static CSubCallback g_SubCb;